from __future__ import annotations
from typing import Optional, List
from sqlalchemy.orm import Mapped, mapped_column, relationship
from extensions import db
from werkzeug.security import generate_password_hash, check_password_hash
from datetime import datetime
from flask import current_app
from flask_jwt_extended import create_access_token
from sqlalchemy import func

class User(db.Model):
    """用户模型"""
    from typing import TypeVar
    T = TypeVar('T', bound='User')
    __tablename__ = 'users'
    
    # 自增主键ID，系统内部使用的唯一标识
    id: Mapped[int] = mapped_column(db.Integer, primary_key=True)
    # 用户唯一标识符（UUID格式），用于外部系统关联和API调用
    user_id: Mapped[str] = mapped_column(db.String(36), unique=True, index=True)
    # 用户姓名，员工或客户的真实姓名
    name: Mapped[str] = mapped_column(db.String(64), nullable=False)
    # 性别，用户的性别信息（男/女）
    gender: Mapped[Optional[str]] = mapped_column(db.String(10))
    # 联系电话，用户的手机号码，用于登录和联系
    phone: Mapped[str] = mapped_column(db.String(20), unique=True, nullable=False)
    # 出生日期，用户的生日信息，用于会员管理
    birthday: Mapped[Optional[datetime]] = mapped_column(db.Date)
    # 用户备注信息，存储用户的特殊需求或偏好等补充信息
    remarks: Mapped[Optional[str]] = mapped_column(db.Text)
    # 密码哈希值，存储加密后的密码，确保安全性
    password_hash: Mapped[Optional[str]] = mapped_column(db.String(128))
    
    # 销售员ID，关联到创建该用户的销售员
    staff_id: Mapped[Optional[str]] = mapped_column(db.String(36), index=True)

    @staticmethod
    def verify_token(token: str) -> dict:
        """验证JWT令牌并返回解码后的声明"""
        from flask_jwt_extended import decode_token
        
        try:
            decoded = decode_token(token, current_app.config['JWT_SECRET_KEY'])
            user = User.query.filter_by(user_id=decoded['sub']).first()
            if not user:
                raise ValueError("无效的用户")
            return decoded
        except Exception as e:
            current_app.logger.error(f"令牌验证失败: {str(e)}")
            raise
    # 用户角色，多个角色用逗号分隔（如：admin-管理员,staff-员工,customer-顾客）
    roles: Mapped[str] = mapped_column(db.String(128), nullable=False)
    # 所属店铺ID，标识用户所属的店铺（非外键关联，手动查询）
    store_id: Mapped[Optional[str]] = mapped_column(db.String(36), index=True)
    # 管理层级ID，关联hierarchies表，确定用户在组织中的管理层级
    manager_hierarchy_id: Mapped[Optional[str]] = mapped_column(db.String(36), db.ForeignKey('hierarchies.hierarchy_id'), index=True)
    # 记录创建时间，用户信息首次创建的时间戳
    created_at: Mapped[datetime] = mapped_column(
        db.DateTime,
        server_default=func.now(),  # 优先使用数据库当前时间
        default=datetime.utcnow     # 使用Python系统时间作为后备
    )
    # 记录最后更新时间，用户信息最后一次修改的时间戳
    updated_at: Mapped[datetime] = mapped_column(
        db.DateTime,
        server_default=func.now(),  # 优先使用数据库当前时间
        default=datetime.utcnow,    # 使用Python系统时间作为后备
        onupdate=datetime.utcnow    # 更新时使用Python系统时间
    )
    # 软删除标记，True表示已删除，False表示正常
    is_deleted: Mapped[bool] = mapped_column(db.Boolean, default=False)
    
    # 关联关系定义
    # 层级关联（一对多：一个层级可以有多个用户）
    hierarchy = relationship('Hierarchy', backref=db.backref('users', lazy='dynamic'))
    
    @property
    def password(self):
        raise AttributeError('密码不可读')
    
    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)
    
    def check_password(self, password: str) -> bool:
        """验证密码
        
        Args:
            password: 待验证的密码
            
        Returns:
            bool: 密码是否正确
        """
        if self.password_hash is None:
            return False
        return check_password_hash(self.password_hash, password)
    
    def __init__(self, user_id: str, name: str, phone: str, roles: str,
                 store_id: Optional[str] = None, manager_hierarchy_id: Optional[str] = None,
                 password: Optional[str] = None, gender: Optional[str] = None,
                 birthday: Optional[datetime] = None, remarks: Optional[str] = None,
                 staff_id: Optional[str] = None) -> None:
        self.user_id = user_id
        self.name = name
        self.phone = phone
        self.roles = roles
        self.store_id = store_id
        self.manager_hierarchy_id = manager_hierarchy_id
        self.gender = gender
        self.birthday = birthday
        self.remarks = remarks
        if password:
            self.password = password

    def get_roles(self) -> List[str]:
        """获取用户角色列表"""
        return self.roles.split(',') if self.roles else []

    @property
    def is_admin(self) -> bool:
        """判断是否为管理员"""
        return 'admin' in self.get_roles()

    def generate_token(self) -> str:
        """生成JWT令牌"""
        identity = {'user_id': self.user_id, 'is_admin': self.is_admin}
        return create_access_token(
            identity=identity,
            expires_delta=current_app.config['JWT_ACCESS_TOKEN_EXPIRES']
        )

    def to_dict(self) -> dict:
        """转换为字典"""
        return {
            'id': self.id,
            'user_id': self.user_id,
            'name': self.name,
            'phone': self.phone,
            'roles': self.get_roles(),
            'store_id': self.store_id,
            'manager_hierarchy_id': self.manager_hierarchy_id,
            'created_at': self.created_at.isoformat() if self.created_at else None,
            'updated_at': self.updated_at.isoformat() if self.updated_at else None,
            'gender': self.gender,
            'birthday': self.birthday.isoformat() if self.birthday else None,
            'remarks': self.remarks,
            'is_deleted': self.is_deleted,
            'staff_id': self.staff_id
        }